#ifndef STREAM_SERVER_G711A_H
#define STREAM_SERVER_G711A_H

#include <liveMedia/liveMedia.hh>
#include <BasicUsageEnvironment/BasicUsageEnvironment.hh>
#include <groupsock/GroupsockHelper.hh>
#include <memory>

#include "media_stream.h"
#include "base_log.h"
#include "base_block_queue.h"

namespace El {
namespace StreamServer {

class G711aAudioSource : public FramedSource {
public:
    static G711aAudioSource *createNew(UsageEnvironment &env, int32_t ch, int32_t type);

protected:
    G711aAudioSource(UsageEnvironment &env, int32_t ch, int32_t type);
    virtual ~G711aAudioSource();

private:
    static void deliverFrame0(void *clientData);
    virtual void doGetNextFrame() override;
    void deliverFrame();
    void onFrame(const Media::MediaFramePtr &frame);
    void bufferExcessData(const uint8_t *data, size_t size);

private:
    int32_t fCh;
    int32_t fType;
    int32_t fHandle;
    std::unique_ptr<Base::BlockingQueue<Media::MediaFramePtr>> queue_;
    std::vector<uint8_t> excessDataBuffer;
    Media::MediaFramePtr currentFrame_;
};

class G711aAudioSubsession : public OnDemandServerMediaSubsession {
public:
    static G711aAudioSubsession *createNew(UsageEnvironment &env, int32_t ch, int32_t type, bool reuseFirstSource);

protected:
    G711aAudioSubsession(UsageEnvironment &env, int32_t ch, int32_t type, bool reuseFirstSource);
    virtual ~G711aAudioSubsession();

private:
    virtual FramedSource *createNewStreamSource(unsigned clientSessionId, unsigned &estBitrate) override;
    virtual RTPSink *createNewRTPSink(Groupsock *rtpGroupsock,
                                      unsigned char rtpPayloadTypeIfDynamic,
                                      FramedSource *inputSource) override;

private:
    int32_t fCh;
    int32_t fType;
};
} // namespace StreamServer
} // namespace El

#endif // STREAM_SERVER_G711A_H